home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / frntsdk1.cpt / Frontier SDK 1.0 ƒ / Menu Sharer Program / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-10-21  |  8.7 KB  |  494 lines

  1.  
  2. /*⌐ Copyright 1989-1991 UserLand Software, Inc.  All Rights Reserved.*/
  3.  
  4.  
  5. /*
  6. Last Update: 9/29/91 DW.
  7.  
  8. Briefly -- this is a very small program that demonstrates the UserLand Menu Sharing
  9. protocol. For detailed info, see the enclosed technote -- "Sharing Menus with Frontier."
  10.  
  11. You can search the source code for menu sharing highlights by searching for the
  12. following string: "See Step #". The step numbers refer to steps in the "Cookbook"
  13. section of the enclosed technote.
  14.  
  15. Please contact UserLand Software at AppleLink USERLAND.DTS or at 415-325-5700 for
  16. further information on the Menu Sharing protocol. 
  17.  
  18. We hope you like menu sharing and add it to your Macintosh application.
  19.  
  20. Thanks!
  21.  
  22. Dave Winer
  23. UserLand Software
  24. */
  25.  
  26.  
  27. #include <menusharing.h> /*See Step #6*/
  28.  
  29. #include <iac.h> /*See Step #5*/
  30.  
  31.  
  32. #define applemenu 128 /*the resource id of the apple menu*/
  33.  
  34. #define aboutitem 1 /*the about command*/
  35.  
  36. #define filemenu 129 /*resource id of file menu, shared menus appear to right of this*/
  37.  
  38. #define firstsharedmenu filemenu+1 /*resource id for first shared menu*/
  39.  
  40. #define quititem 1 /*the single item in the file menu -- this is a very simple program!*/
  41.  
  42. MenuHandle happlemenu, hfilemenu; /*the two fixed, non-shared menus in this program*/
  43.  
  44. WindowPtr mainwindow = nil; /*the menu sharing test window*/
  45.  
  46. Str255 windowmessage; /*the message that's displayed in the main window*/
  47.  
  48. short flexitmainloop = false; /*when true we fall thru the main event loop*/
  49.     
  50.     
  51.  
  52.  
  53. static void copystring (Str255 source, Str255 dest) {
  54.  
  55.     /*
  56.     create a copy of source in dest.  copy the length byte and
  57.     all the characters in the source string.
  58.  
  59.     assume the strings are pascal strings, with the length byte in
  60.     the first character of the string.
  61.     */
  62.  
  63.     register short i, len;
  64.     
  65.     len = (short) source [0];
  66.     
  67.     for (i = 0; i <= len; i++) 
  68.         dest [i] = source [i];
  69.     } /*copystring*/
  70.  
  71.  
  72. static void ellipsize (Str255 s, short width) {
  73.  
  74.     /*
  75.     if the string fits inside the given number of pixels, fine -- do nothing
  76.     and return.
  77.     
  78.     if not, return a string that does fit, with ellipses representing the 
  79.     deleted characters.  ellipses are generated by pressing option-semicolon.
  80.     */
  81.     
  82.     register char len;
  83.     register short newwidth;
  84.     
  85.     if ((newwidth = StringWidth (s)) <= width) /*nothing to do, the string fits*/
  86.         return;
  87.     
  88.     len = s [0]; /* current length in characters*/
  89.     
  90.     width -= CharWidth ('╔'); /* subtract width of ellipses*/
  91.         
  92.     do { /*until it fits (or we run out of characters)*/
  93.     
  94.         newwidth -= CharWidth (s [len]);
  95.         
  96.         --len;
  97.     } while ((newwidth > width) && (len != 0));
  98.     
  99.     ++len; /*make room for the ellipses*/
  100.     
  101.     s [len] = '╔'; 
  102.     
  103.     s [0] = (char) len;
  104.     } /*ellipsize*/
  105.  
  106.  
  107. static void centerstring (Rect r, Str255 s) {
  108.     
  109.     /*
  110.     draw the string in the current font, size and style, centered inside
  111.     the indicated rectangle.
  112.     */
  113.     
  114.     register short rh = r.bottom - r.top;
  115.     register short rw = r.right - r.left;
  116.     register short h, v;
  117.     FontInfo fi;
  118.     
  119.     GetFontInfo (&fi);
  120.     
  121.     ellipsize (s, rw); /*make sure it fits inside the rectangle, width-wise*/
  122.     
  123.     h = r.left + ((rw - StringWidth (s)) / 2);
  124.     
  125.     v = r.top + ((rh - (fi.ascent + fi.descent)) / 2) + fi.ascent;
  126.     
  127.     MoveTo (h, v);
  128.     
  129.     ClipRect (&r);
  130.     
  131.     DrawString (s);
  132.     } /*centerstring*/
  133.  
  134.  
  135. static void setfontsizestyle (short fontnum, short fontsize, short fontstyle) {
  136.  
  137.     TextFont (fontnum);
  138.     
  139.     TextSize (fontsize);
  140.     
  141.     TextFace (fontstyle);
  142.     } /*setfontsizestyle*/
  143.     
  144.     
  145. static void updatemainwindow (void) {
  146.     
  147.     Rect r;
  148.     Str255 s;
  149.     
  150.     r = (*mainwindow).portRect;
  151.     
  152.     EraseRect (&r);
  153.     
  154.     setfontsizestyle (helvetica, 12, 0);
  155.     
  156.     centerstring (r, windowmessage);
  157.     
  158.     NumToString (FreeMem () / 1024, s);
  159.     
  160.     MoveTo (r.left + 3, r.bottom - 3);
  161.     
  162.     setfontsizestyle (geneva, 9, 0);
  163.     
  164.     DrawString (s);
  165.     
  166.     DrawString ("\pK");
  167.     } /*updatemainwindow*/
  168.     
  169.     
  170. static Boolean setwindowmessage (Str255 s) {
  171.     
  172.     copystring (s, windowmessage);
  173.     
  174.     SetPort (mainwindow);
  175.     
  176.     updatemainwindow ();
  177.     
  178.     return (true);
  179.     } /*setwindowmessage*/
  180.  
  181.  
  182. static Boolean initmainwindow (void) {
  183.     
  184.     register WindowPtr w;
  185.     
  186.     w = mainwindow = GetNewWindow (128, nil, (WindowPtr) -1);
  187.     
  188.     if (w == nil)
  189.         return (false);
  190.     
  191.     ShowWindow (w);
  192.     
  193.     return (true);
  194.     } /*initmainwindow*/
  195.  
  196.  
  197. static void handleupdate (EventRecord *ev) {
  198.     
  199.     register WindowPtr w;
  200.     
  201.     w = (WindowPtr) (*ev).message;
  202.     
  203.     BeginUpdate (w);
  204.     
  205.     SetPort (w);
  206.     
  207.     updatemainwindow ();
  208.     
  209.     EndUpdate (w);
  210.     } /*handleupdate*/
  211.  
  212.  
  213. static void handledrag (EventRecord *ev, WindowPtr w) {
  214.     
  215.     Rect r;
  216.  
  217.     r = qd.screenBits.bounds; 
  218.     
  219.     r.top = r.top + GetMBarHeight (); 
  220.     
  221.     InsetRect (&r, 4, 4);
  222.     
  223.     DragWindow (w, (*ev).where, &r);
  224.     } /*handledrag*/
  225.  
  226.  
  227. static void handlemenu (long codeword) {
  228.     
  229.     register short idmenu, iditem;
  230.     
  231.     iditem = LoWord (codeword);
  232.     
  233.     idmenu = HiWord (codeword);
  234.     
  235.     if (SharedMenuHit (idmenu, iditem)) /*See Step #3*/    
  236.         goto exit;
  237.     
  238.     switch (idmenu) {
  239.     
  240.         case applemenu: 
  241.             switch (iditem) {
  242.                 
  243.                 case aboutitem:
  244.                     Alert (262, nil);
  245.                     
  246.                     break;
  247.             
  248.                 default: {
  249.                 
  250.                     Str255 s;
  251.                     
  252.                     GetItem (happlemenu, iditem, s);
  253.                     
  254.                     OpenDeskAcc (s);
  255.                     
  256.                     break;
  257.                     }
  258.                 } /*switch*/
  259.             
  260.             break; /*apple menu*/
  261.  
  262.         case filemenu: 
  263.             switch (iditem) {
  264.                 
  265.                 case quititem:
  266.                 
  267.                     flexitmainloop = true;
  268.                     
  269.                     break;
  270.                 } /*switch*/
  271.             
  272.             break; /*file menu*/
  273.             
  274.         } /*switching on which menu was invoked*/
  275.         
  276.     exit:
  277.     
  278.     HiliteMenu (0);
  279.     } /*handlemenu*/
  280.  
  281.  
  282. static void handlemouse (EventRecord *ev) {
  283.  
  284.     register short part;
  285.     WindowPtr w;
  286.     
  287.     part = FindWindow ((*ev).where, &w);
  288.     
  289.     if (w != nil) 
  290.     
  291.         if (w != FrontWindow ()) { /*just like all other Mac programs*/
  292.             
  293.             SelectWindow (w);
  294.                             
  295.             return; /*the mouse click is consumed by the bringtofront operation*/
  296.             }
  297.     
  298.     switch (part) {
  299.     
  300.         case inMenuBar: 
  301.             handlemenu (MenuSelect ((*ev).where)); 
  302.             
  303.             break;
  304.         
  305.         case inSysWindow:
  306.             SystemClick (ev, w); 
  307.             
  308.             break;
  309.         
  310.         case inDrag:
  311.             handledrag (ev, w);
  312.             
  313.             break;
  314.             
  315.         } /*switch*/
  316.     } /*handlemouse*/
  317.  
  318.  
  319. static void handlekeystroke (EventRecord *ev) { /*See Step #4*/
  320.  
  321.     register char ch = (*ev).message & charCodeMask;
  322.     
  323.     if (SharedScriptRunning ()) { /*cmd-period terminates the script*/
  324.     
  325.         if (((*ev).modifiers & cmdKey) && (ch == '.')) { 
  326.             
  327.             CancelSharedScript (); /*cancel the shared menu script, if one is running*/
  328.         
  329.             return;
  330.             }
  331.         }
  332.     
  333.     handlemenu (MenuKey (ch)); /*not cmd-period, process the normal way*/
  334.     } /*handlekeystroke*/
  335.  
  336.  
  337. static void handleevent (EventRecord *ev) {
  338.     
  339.     switch ((*ev).what) {
  340.     
  341.         case keyDown: case autoKey: 
  342.             handlekeystroke (ev);
  343.             
  344.             break;
  345.             
  346.         case mouseDown:
  347.             handlemouse (ev);
  348.             
  349.             break;
  350.         
  351.         case updateEvt:
  352.             handleupdate (ev);
  353.             
  354.             break;
  355.             
  356.         case kHighLevelEvent:
  357.             AEProcessAppleEvent (ev);
  358.             
  359.             break;
  360.         } /*switch*/
  361.     } /*handleevent*/
  362.  
  363.  
  364. static void maineventloop (void) {
  365.     
  366.     EventRecord ev;
  367.     
  368.     while (!flexitmainloop) {
  369.         
  370.         if (WaitNextEvent (everyEvent, &ev, 1, nil)) 
  371.             handleevent (&ev);
  372.         
  373.         CheckSharedMenus (firstsharedmenu); /*See Step #2*/
  374.         } /*while*/
  375.     } /*maineventloop*/
  376.  
  377.  
  378. static void initmenus (void) {
  379.     
  380.     /*
  381.     set up our apple and file menus.  nothing fancy.
  382.     */
  383.     
  384.     happlemenu = GetMenu (applemenu); 
  385.     
  386.     AddResMenu (happlemenu, 'DRVR'); 
  387.     
  388.     InsertMenu (happlemenu, 0); 
  389.     
  390.     hfilemenu = GetMenu (filemenu); 
  391.     
  392.     InsertMenu (hfilemenu, 0);
  393.     
  394.     DrawMenuBar ();
  395.     } /*initmenus*/
  396.  
  397.  
  398. static void initmacintosh (void) {
  399.  
  400.     /*
  401.     the magic stuff that every Macintosh application needs to do 
  402.     before doing anything else.
  403.     */
  404.  
  405.     register short i;
  406.         
  407.     MaxApplZone ();
  408.     
  409.     for (i = 0; i < 10; i++) 
  410.         MoreMasters ();
  411.     
  412.     InitGraf (&qd.thePort);
  413.     
  414.     InitFonts ();
  415.     
  416.     FlushEvents (everyEvent, 0);
  417.     
  418.     InitWindows ();
  419.     
  420.     InitMenus ();
  421.     
  422.     TEInit ();
  423.     
  424.     InitDialogs (nil);
  425.     
  426.     InitCursor ();
  427.     
  428.     for (i = 0; i < 5; i++) { /*register with Multifinder*/
  429.         
  430.         EventRecord ev;
  431.         
  432.         EventAvail (everyEvent, &ev); /*see TN180 -- splash screen*/
  433.         } /*for*/
  434.     } /*initmacintosh*/
  435.  
  436.  
  437. static pascal OSErr quitroutine (AppleEvent *event, AppleEvent *reply, long refcon) {
  438.     
  439.     flexitmainloop = true;
  440.     
  441.     return (noErr);
  442.     } /*quitroutine*/
  443.     
  444.     
  445. static pascal OSErr setmessageverb (AppleEvent *event, AppleEvent *reply, long refcon) {
  446.  
  447.     Str255 s;
  448.     
  449.     if (SharedScriptCancelled (event, reply)) /*See Step #5*/
  450.         return (noErr);
  451.     
  452.     IACglobals.event = event;
  453.     
  454.     IACglobals.reply = reply;
  455.     
  456.     if (!IACgetstringparam ((OSType) keyDirectObject, s))
  457.         return (false);
  458.     
  459.     IACreturnboolean (setwindowmessage (s));
  460.     
  461.     return (noErr);
  462.     } /*setmessageverb*/
  463.     
  464.  
  465. void main (void) {
  466.     
  467.     initmacintosh ();
  468.     
  469.     if (!InitSharedMenus ()) /*See Step #1*/
  470.         goto error;
  471.  
  472.     if (AEInstallEventHandler ('TEST', 'smsg', (ProcPtr) setmessageverb, 0, false) != noErr)
  473.         goto error;
  474.     
  475.     if (AEInstallEventHandler (kCoreEventClass, kAEQuitApplication, (ProcPtr) quitroutine, 0, false) != noErr)
  476.         goto error;
  477.     
  478.     initmenus ();
  479.     
  480.     initmainwindow ();
  481.     
  482.     maineventloop ();
  483.         
  484.     ExitToShell ();
  485.     
  486.     error:
  487.     
  488.     Alert (261, nil); /*this application requires system 7.0 or higher*/
  489.         
  490.     ExitToShell ();
  491.     } /*main*/
  492.  
  493.  
  494.